﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Drawing;
using System.Drawing.Imaging;

namespace LowLevelGraphics.SeamCarving
{
    /// <summary>
    /// 
    /// </summary>
    public static class Common
    {
        // Get the "energy" of a pixel in terms of luminance
        // If outside the bounds of the bitmap, return maximum energy value
        public static byte GetValue(BitmapData bmd, Size size, int x, int y)
        {
            if (x >= 0 && x < size.Width && y >= 0 && y < size.Height)
            {
                unsafe
                {
                    byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride) + (x * 3);
                    // RGB to luminance formula
                    return (byte)((0.2126 * row[2]) + (0.7152 * row[1]) +
                    (0.0722 * row[0]));
                }
            }
            else
            {
                return byte.MaxValue;
            }
        }

        public static byte GetColor(BitmapData bmd, Size size, int x, int y, int index)
        {
            if (x >= 0 && x < size.Width && y >= 0 && y < size.Height)
            {
                unsafe
                {
                    byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride) + (x * 3);
                    return row[index];

                }
            }
            else
            {
                // Pixel is out of bounds, so return maximum energy
                return byte.MaxValue;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="array"></param>
        /// <param name="direction"></param>
        /// <param name="offset"></param>
        /// <param name="shiftIndex"></param>
        /// <param name="toIndex"></param>
        /// <param name="emptyValue"></param>
        public static void ShiftArray<T>(T[,] array, Direction direction, int offset, int shiftIndex, int toIndex, object emptyValue)
        {
            int x = 0, y = 0;
            int xMax = int.MaxValue, yMax = int.MaxValue;
            int xInc = 0, yInc = 0; // x and y increments
            // Set initial values
            if (direction == Direction.Vertical)
            {
                x = shiftIndex;
                y = offset;
                xMax = toIndex - 1;
                xInc = 1;
            }
            else if (direction == Direction.Horizontal)
            {
                x = offset;
                y = shiftIndex;
                yMax = toIndex - 1;
                yInc = 1;
            }
            // Iterate
            while (x < xMax && y < yMax)
            {
                array[x, y] = array[x + xInc, y + yInc];
                // Increment
                x += xInc;
                y += yInc;
            }
            // Set value at edge of array
            array[x, y] = (T)emptyValue;
        }
    }
}
